package ge.modules.drawables;

import ge.engine.Log;
import ge.engine.Positionable;
import ge.exceptions.FunctionNonSuported;
import ge.lowlevel.DrawEngine;
import ge.lowlevel.box2d.FactoryBox2D;

import java.util.ArrayList;

/**
 * 
 * @author Abel
 *	A shape is a general figure composed by points.
 *	Shape won't be optimized to be drawn only when you can see it in the screen.
 * 	It will be drawn every time.
 */
public class ShapeModule extends DrawableObject {

	private ArrayList<Double> xs;
	private ArrayList<Double> ys;
	private double xpos,ypos;
	private Color c;
	private double minx = 0, miny = 0;
	private double maxx = 0, maxy = 0;
	public ShapeModule()
	{
		super(0, 0);
		xs = new ArrayList<Double>();
		ys = new ArrayList<Double>();
		xpos = ypos = 0 ;
		c = new Color();
	}
	/**
	 *  
	 * @param c Color of the shape
	 */
	public void setColor(Color c)
	{
		this.c = c;
	}
	/**
	 * 
	 * @return The actual color
	 */
	public Color getColor()
	{
		return c;
	}
	
	/**
	 * 	Sets the points in one String with the next format: "p1x p1y p2x p2y ...".
	 * 	If the point index doesn't exits, adds the point to the list
	 * @param puntos String with pairs x y of points
	 * @param scale May you need resize every point to a different scale. If not, use 1
	 */
	public void setPoints(String puntos,  double  scale)
	{
		String[] ps = puntos.split(" +");
	
		for(int i = 0; i < ps.length; i+=2)
		{
			double fx = Double.parseDouble(ps[i]);
			double fy = Double.parseDouble(ps[i+1]);
			
			//Log.write(fx*scale+"   "+fy*scale+"  "+scale+" "+fx);
			if(i < xs.size()*2)
				this.setIndex(i/2, fx*scale,fy*scale);
			else
				this.addPoint(fx*scale, fy*scale);
			 
		}
		 

	}
	/**
	 * 	Adds a new point to the shape
	 * @param x Position
	 * @param y Position
	 */
	public void addPoint(double x, double y)
	{
		xs.add(x);
		ys.add(y);
		updateArea(x,y);
	}
	/**
	 * 	Get the position of the index in the shape
	 * @param x Point x
	 * @param y Point y
	 * @return index, o -1 if that point doesn't exist.
	 */
	public int getIndex(double x, double y)
	{
		for(int i = 0; i < xs.size(); i++)
		{
			if(xs.get(i) == x && ys.get(i) == y)
				return i;
		}
		return -1;
	}
	/**
	 * 	Modifies the value of the point in the index position
	 * @param index Has to be between 0 and number of points
	 * @param x New x value
	 * @param y New y value
	 */
	public void setIndex(int index, double x, double y)
	{
		if(index >= 0 && index < xs.size())
		{
			xs.set(index, x);
			ys.set(index, y);
			updateArea(x,y);
		}
		
	}
	/**
	 * 	Removes that point 
	 * @param index  Has to be between 0 and number of points
	 */
	public void remove(int index)
	{
		if(index >= 0 && index < xs.size())
		{
			xs.remove(index); ys.remove(index);
			calculateSquareArea();
		}
	}
	/**
	 *  Updates the square area size
	 * @param newx
	 * @param newy
	 */
	private void updateArea(double newx,double newy)
	{
		if(xs.size() > 1)
		{
			minx = Math.min(minx, newx);
			miny = Math.min(miny, newy);
			maxx = Math.max(maxx, newx);
			maxy = Math.max(maxy, newy);
		}
		else
		{
			minx =  maxx = newx;
			miny = maxy = newy;
		}
		imageSquare.setArea(maxx-minx, maxy-miny);
	}
	/**
	 * Do the same but look all points. It will be needed when you remove a point.
	 */
	private void calculateSquareArea()
	{
		double x1 = Double.MAX_VALUE-10, y1 = Double.MAX_VALUE-10;
	    double x2 = Double.MIN_VALUE +10, y2 = Double.MIN_VALUE+10;
	    minx = 0; miny = 0; maxx =0; maxy= 0;
		for(int i = 0 ; i < xs.size();i++)
		{
			x1 = Math.min(x1, xs.get(i));
			y1 = Math.min(y1, ys.get(i));
			x2 = Math.max(x1, xs.get(i));
			y2 = Math.max(y1, ys.get(i));
		}
		minx = x1; miny = y1; maxx =x2; maxy= y2;
		imageSquare.setArea(x1+(x2-x1), y1+(y2-y1));
	}
	/**
	 * 
	 * @return Total of points of the figure
	 */
	public int getTotalPoints()
	{
		return xs.size();
	}
	 
	@Override
	public void update()
	{
		super.update();
		//Log.write("Update "+getX()+","+getY());
	}
	@Override
	public void draw() 
	{
		if(!isVisible())
			return;
		if(!isInsideScreen())
			return;
		if(getTotalPoints() > 1)
		{
			 
			try
			{
				DrawEngine.get().setLayer(layer);
				DrawEngine.get().setPath(true);
				DrawEngine.get().moveTo(xs.get(0)+getRelativeX(), ys.get(0)+getRelativeY());
				for(int i = 0; i < xs.size(); i++)
				{
				 
					//Log.write(((xs.get(i)+getRelativeX())/FactoryBox2D.getActualWorld().getScale())+"  "+((ys.get(i)+getRelativeY())/FactoryBox2D.getActualWorld().getScale()));
					DrawEngine.get().lineTo(xs.get(i)+getRelativeX(), ys.get(i)+getRelativeY());
				}
				DrawEngine.get().lineTo(xs.get(0)+getRelativeX(), ys.get(0)+getRelativeY());
				//Rellena
				DrawEngine.get().setColor(c.getR(), c.getG(), c.getB(),c.getA());
				DrawEngine.get().fill();
				
				//DrawEngine.get().setPath(false);
				DrawEngine.get().setColor(0, 0,0);
			} 
			catch (FunctionNonSuported e) 
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		
	}

	
}
